package com.java.concurrent;

/**
 * 线程中断
 * 线程中断的情况
 * 1. 许多线程是死循环，停止程序时需要关闭线程
 * 2. 用户主动取消任务执行
 * 3. 任务执行超时线程停止
 */
public class ThreadInterruptKnowledge {


    // Java中停止一个线程的主要机制是中断，中断并不是强迫终止一个线程，而是一种协作机制
    // 是线程传递的一个取消信号，由线程来决定如何以及何时退出
    public static class ThreadInterrupt {
//        public  void stop(); //该方法已过时
//        public boolean isInterrupted(); // 返回对应线程的中断标志是否为true
//        public void interrupt(); //实例方法，调用需要通过线程对象
//        public  static boolean interrupted(); //静态方法，实际会调用Thread。currentThread()操作当前线程 返回当前线程的中断标志位是否为true，同时会清空中断标志位
    }

    public static class WhatIsInterrupted {

        // Runnable状态的线程，且没有IO操作，interrupt()只会设置线程中断标志
        // 线程应该在运行过程中合适的位置检查中断标志
        public class InterruptRunnableDemo extends Thread {
            @Override
            public void run() {
                while(!Thread.currentThread().isInterrupted()) {

                }
                System.out.println("done");
            }
        }

        // 线程调用join/wait/sleep方法后进入WAITING或TIMED_WAITING状态，在这些状态时对象线程调用interrupt()会使线程抛出InterruptedException
        // 抛出异常后，中断标志位会清空，而不是被设置
        // 捕获到InterruptException后通常表示希望技术线程，处理方式有两种
        // 1. 向上传递异常，使得方法变成可中断的方法，由调研者进行处理
        // 2. 有些清空不能向上传异常，则应捕获异常并处理，清理后调用Thread的interrupt方法设置中断标志位
        public static class InterruptWaitingDemo extends Thread {

            public static void main(String[] args) {
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            System.out.println(isInterrupted());
                        }
                    }
                };

                thread.start();
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {

                }
                thread.interrupt();
            }
        }


        // 如果线程在等待锁，线程对象调用interrupt()只会设置线程中断标志位，线程依然会处于BLOCKED状态
        // interrupt()并不能是一个在等待锁的线程真正中断
        public static class InterruptBlockedDemo {
            private static Object lock = new Object();
            private static class A extends Thread {
                @Override
                public void run() {
                    synchronized (lock) {
                        while (!Thread.currentThread().isInterrupted()) {

                        }
                        System.out.println("exit");
                    }
                }
            }

            public static void test() throws InterruptedException {
                synchronized (lock) {
                    A a = new A();
                    a.start();
                    Thread.sleep(1000);
                    a.interrupt(); //使用interrupt()并不会结束线程，而是只会设置线程中断标志，不会使其从锁等待对抗中出来
                    a.join();
                }
            }

            public static void main(String[] args) throws InterruptedException{
                test();
            }
        }
    }

    // interrupt只是一种协作机制，不一定会真正中断线程
    // 以线程提供服务的程序模块应该封装取消/关闭操作，提供单独的取消/关闭方法给调用者
    public static class HowToStopThread {

    }
}
